
#include "uart.h"
#include "word.h"
#include "beep.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
#include <termios.h> 
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>

//全局变量 
int Lux = 0;        //光照强度 
int Temperature = 0;    //温度 
int AirPressure = 0;    //气压
int Humidity = 0;       //湿度 
int Altitude = 0;       //海拔

int beep_flag = 0;      //蜂鸣器的标志位：1响，0灭
int led_flag = 0;       //led灯的标志位：1亮，0灭

//串口的初始化 
int init_serial(const char *file, int baudrate)
{ 
    int fd;
    
    fd = open(file, O_RDWR);
    if (fd == -1)
    {
        perror("open device error:");
        return -1;
    }

    struct termios myserial;
    //清空结构体
    memset(&myserial, 0, sizeof (myserial));
    //O_RDWR               
    myserial.c_cflag |= (CLOCAL | CREAD);
    //设置控制模式状态，本地连接，接受使能
    //设置 数据位
    myserial.c_cflag &= ~CSIZE;   //清空数据位
    myserial.c_cflag &= ~CRTSCTS; //无硬件流控制
    myserial.c_cflag |= CS8;      //数据位:8

    myserial.c_cflag &= ~CSTOPB;//   //1位停止位
    myserial.c_cflag &= ~PARENB;  //不要校验
    //myserial.c_iflag |= IGNPAR;   //不要校验
    //myserial.c_oflag = 0;  //输入模式
    //myserial.c_lflag = 0;  //不激活终端模式

    switch (baudrate)
    {
        case 9600:
            cfsetospeed(&myserial, B9600);  //设置波特率
            cfsetispeed(&myserial, B9600);
            break;
        case 115200:
            cfsetospeed(&myserial, B115200);  //设置波特率
            cfsetispeed(&myserial, B115200);
            break;
        case 19200:
            cfsetospeed(&myserial, B19200);  //设置波特率
            cfsetispeed(&myserial, B19200);
            break;
    }
    
    /* 刷新输出队列,清除正接受的数据 */
    tcflush(fd, TCIFLUSH);

    /* 改变配置 */
    tcsetattr(fd, TCSANOW, &myserial);

    return fd;
}


//解析数据 
void parse_data( unsigned char buf[], int n )
{
    if( buf[2] == 0x15 )    //光照强度
    {
        //先覆盖上一次的数据
        show_number( 300, 100, Lux, 0xFFC1C1 );

        Lux = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
        Lux = Lux / 100;

        printf("Lux = %d\n", Lux );

        //在屏幕上显示数据，并做处理
        show_number( 300, 100, Lux, 0xFF0000 );

        if( Lux > 100 && led_flag == 1 ) 
        {
            led_flag = 0;
            beep_LED_ctrl( LED1, 0 );   //熄灭灯1
        }
        else if( Lux < 10 && led_flag == 0 )
        {
            led_flag = 1;
            beep_LED_ctrl( LED1, 1 );   //点亮灯1
        }

    }
    else if( buf[2] == 0x45 )   //温度、气压、湿度、海拔
    {
        // 先覆盖上一次的数据
        show_number( 300, 200, Temperature, 0xFFC1C1 );
        show_number( 300, 300, AirPressure, 0xFFC1C1 );
        show_number( 300, 400, Humidity, 0xFFC1C1 );
        show_number( 300, 500, Altitude, 0xFFC1C1 );

        Temperature = (buf[4]<<8) | buf[5];
        Temperature = Temperature / 100;

        AirPressure =  (buf[6]<<24) | (buf[7]<<16) | (buf[8]<<8) | buf[9];
        AirPressure = AirPressure / 100;

        Humidity = (buf[10]<<8) | buf[11];
        Humidity = Humidity / 100;

        Altitude = (buf[12]<<8) | buf[13];

            printf("Temperature = %d\n", Temperature );
            printf("AirPressure = %d\n", AirPressure );
            printf("Humidity = %d\n", Humidity );
            printf("Altitude = %d\n", Altitude );

        //在屏幕上显示数据，并做处理
        show_number( 300, 200, Temperature, 0xFF0000 );
        show_number( 300, 300, AirPressure, 0xFF0000 );
        show_number( 300, 400, Humidity, 0xFF0000 );
        show_number( 300, 500, Altitude, 0xFF0000 );

    }
}

//获取GY39传感器的数据
void get_GY39()
{
    //1.打开串口，并初始化 
    int fd = init_serial( UART0 , 9600 );
    if( fd == -1 )
    {
        return ;
    }

    //unsigned char cmd[3] = { 0xA5, 0x81, 0x26 };    //光照强度 
    //unsigned char cmd[3] = { 0xA5, 0x82, 0x27 };    //温度、气压、湿度、海拔
    unsigned char cmd[3] = { 0xA5, 0x83, 0x28 };    //同时获取两种数据

    //2.发送指令
    write( fd, cmd, 3 );

    unsigned char buf[32] = {0};
    unsigned char ch = 0;
    while( 1 )
    {
        //3.接收数据 
            /* 
                帧头，帧头，数据类型，数据量， .... , 校验和 
                0x5A, 0x5A, type,  length,  .... , checksum   
            */

            //先读取第一个 0x5A 
            do 
            {
                read( fd, &ch, 1 );
            }while( ch != 0x5A );

            //再读取第二个0x5A 
            read( fd, &ch, 1 );
            if( ch != 0x5A )
            {
                continue;
            }

            buf[0] = 0x5A;
            buf[1] = 0x5A;

            //读 数据类型 type
            read( fd, &buf[2], 1 );

            //读 数据量 len 
            read( fd, &buf[3], 1 );

            //读 数据 
            int len = buf[3];
            int i;
            for( i=0; i<len; i++ )
            {
                read( fd, &buf[4+i], 1 );
            }

            //读 校验和 
            read( fd, &buf[4+len], 1 );

        //4.解析数据，并显示
        parse_data( buf, 4+len+1 );

        sleep( 1 );
    }

    //5.关闭串口 
    close( fd );
}
